<script setup lang="ts">
import {
  ref,
  nextTick,
  defineProps,
  defineEmits,
  onMounted,
  onUnmounted,
  watch,
  computed
} from 'vue'
import { NButton, NIcon, NInput, NScrollbar } from 'naive-ui'
import { Refresh, Send } from '@vicons/tabler'
import MessageGroup from '@/components/ChatInterface/MessageGroup.vue'
import type {
  Message,
  TextMessage,
  MessageGroup as MessageGroupType,
  MessageGroupList
} from '@/components/ChatInterface/type'

const props = defineProps<{
  initialMessages?: MessageGroupList
}>()

const messages = ref<MessageGroupList>(props.initialMessages || [])
const inputMessage = ref('')
const messageBodyRef = ref<HTMLElement | null>(null)
const botReplyDelay = 2000
const isReplying = ref(false)
const inputHeight = ref(100)
const isSendingDisabled = ref(false)
const isAtBottom = ref(true)

const emit = defineEmits<{
  (e: 'sendMessage', message: string): void
  (e: 'restartConversation'): void
}>()

const previewMessage = computed((): TextMessage => {
  return {
    id: -1,
    content: inputMessage.value,
    sender: 'user',
    timestamp: Date.now(),
    type: 'text'
  }
})

const handleEditMessage = (message: Message, newContent: string) => {
  const groupIndex = messages.value.findIndex((group) =>
    group.messageList.messages.some((m) => m.id === message.id)
  )
  if (groupIndex !== -1) {
    const messageIndex = messages.value[groupIndex].messageList.messages.findIndex(
      (m) => m.id === message.id
    )
    if (
      messageIndex !== -1 &&
      'content' in messages.value[groupIndex].messageList.messages[messageIndex]
    ) {
      ;(messages.value[groupIndex].messageList.messages[messageIndex] as TextMessage).content =
        newContent
    }
  }
}

const handleDeleteMessage = async (groupId: number) => {
  const groupIndex = messages.value.findIndex((group) => group.id === groupId)
  if (groupIndex !== -1) {
    messages.value.splice(groupIndex, 1)
  }
}

const sendMessage = async () => {
  if (inputMessage.value.trim() && !isSendingDisabled.value) {
    try {
      isSendingDisabled.value = true
      const newMessage: TextMessage = {
        id: Date.now(),
        content: inputMessage.value,
        sender: 'user',
        timestamp: Date.now(),
        type: 'text'
      }
      const newMessageGroup: MessageGroupType = {
        id: Date.now(),
        messageList: {
          messages: [newMessage]
        }
      }
      messages.value.push(newMessageGroup)
      await emit('sendMessage', inputMessage.value)
      inputMessage.value = ''
      scrollToBottom()

      setTimeout(() => {
        const botMessage: TextMessage = {
          id: Date.now(),
          content: '',
          sender: 'bot',
          timestamp: Date.now(),
          type: 'text'
        }
        newMessageGroup.messageList.messages.push(botMessage)
        isReplying.value = true
        scrollToBottom()

        setTimeout(() => {
          botMessage.content = '这是机器人回复的消息'
          isReplying.value = false
          isSendingDisabled.value = false
          scrollToBottom()
        }, botReplyDelay)
      }, 1000)
    } catch (error) {
      console.error('Failed to send message:', error)
      // 可以在这里添加错误处理逻辑，比如显示一个错误通知
    } finally {
      isSendingDisabled.value = false
    }
  }
}

const restartConversation = () => {
  messages.value = []
  isSendingDisabled.value = false
  emit('restartConversation')
}

const stopReplying = () => {
  const loadingIndex = messages.value.findIndex((group) =>
    group.messageList.messages.some((m) => 'isLoading' in m && m.isLoading)
  )
  if (loadingIndex !== -1) {
    messages.value[loadingIndex].messageList.messages = messages.value[
      loadingIndex
    ].messageList.messages.filter((m) => !('isLoading' in m) || !m.isLoading)
    isReplying.value = false
    isSendingDisabled.value = false
  }
}

const scrollToBottom = () => {
  nextTick(() => {
    if (messageBodyRef.value && isAtBottom.value) {
      setTimeout(() => {
        messageBodyRef.value?.scrollTo({
          top: messageBodyRef.value.scrollHeight,
          behavior: 'smooth'
        })
      }, 150)
    }
  })
}

const updateInputHeight = () => {
  const inputElement = document.querySelector('.inputs') as HTMLElement
  if (inputElement) {
    inputHeight.value = inputElement.offsetHeight
  }
  scrollToBottom()
}

onMounted(() => {
  window.addEventListener('resize', updateInputHeight)
  setTimeout(updateInputHeight, 100)
})

onUnmounted(() => {
  window.removeEventListener('resize', updateInputHeight)
})

watch(inputMessage, () => {
  nextTick(updateInputHeight)
})

const onScrollHandler = (event: Event) => {
  const target = event.target as HTMLElement
  if (target && target.scrollHeight - target.scrollTop === target.clientHeight) {
    isAtBottom.value = true
  } else {
    isAtBottom.value = false
  }
}

const handleShowLog = (messageId: number) => {
  // Implement logic to show log
  console.log('Show log for message:', messageId)
}

const handleRegenerateMessage = (messageId: number) => {
  // Implement logic to regenerate answer
  console.log('Regenerate answer for message:', messageId)
}
</script>

<template>
  <div
    class="w-full h-full flex flex-col border-solid border-2 border-gray-200 rounded-2xl bg-[#F9FAFB] relative"
    role="region"
    aria-label="Chat Interface"
  >
    <div class="w-full justify-between flex px-5 py-2.5">
      <div class="flex items-center">
        <span class="text-lg font-medium">调试与预览</span>
      </div>
      <div class="flex items-center">
        <NButton class="rounded-xl" type="default" size="small" @click="restartConversation">
          <template #icon>
            <NIcon :component="Refresh"></NIcon>
          </template>
          重新开始
        </NButton>
      </div>
    </div>

    <NScrollbar
      ref="messageBodyRef"
      :style="{ maxHeight: `calc(100vh - ${inputHeight}px - 190px)`, position: 'relative' }"
      content-style="padding: 10px"
      @scroll="onScrollHandler"
    >
      <template v-for="(messageGroup, index) in messages" :key="messageGroup.id">
        <MessageGroup
          :id="messageGroup.id"
          :message-list="messageGroup.messageList"
          :is-replying="isReplying && index === messages.length - 1"
          :is-analysis-mode="false"
          @delete="handleDeleteMessage"
          @show-log="handleShowLog"
          @regenerate="handleRegenerateMessage"
        />
      </template>

      <div v-if="inputMessage" class="mb-4">
        <MessageGroup
          :message-list="{ messages: [previewMessage] }"
          :is-replying="false"
          :is-analysis-mode="false"
        />
      </div>
      <div v-if="isReplying" class="absolute bottom-1.5" style="left: calc(50% - 100px)">
        <div
          class="text-gray-500 flex items-center text-13px gap-1.5 cursor-pointer animate-breathe border border-solid border-gray-200 px-3.5 py-1 rounded-full hover:bg-gray-200 active:bg-gray-300"
          @click="stopReplying"
        >
          <div class="breathing text-lg h-4 w-4 inline-block mr-1.5 animate-breathe"></div>
          停止回复
        </div>
      </div>
    </NScrollbar>

    <NInput
      v-model:value="inputMessage"
      type="textarea"
      :autosize="{ minRows: 3, maxRows: 7 }"
      placeholder="输入消息..."
      class="flex-grow rounded-l-lg focus:outline-none focus:ring-2 focus:ring-blue-500 absolute bottom-5 left-2.5 right-2.5 inputs"
    />
    <div
      class="absolute right-8 bottom-8 flex items-center justify-center w-20 h-10 rounded-lg cursor-pointer transition-all duration-300"
      :class="[
        isSendingDisabled
          ? 'bg-gray-300 cursor-not-allowed'
          : isReplying
            ? 'bg-yellow-500'
            : inputMessage.trim()
              ? 'bg-blue-500 hover:bg-blue-600'
              : 'bg-gray-300 cursor-not-allowed'
      ]"
      @click="!isSendingDisabled && inputMessage.trim() && sendMessage()"
    >
      <NIcon
        :component="Send"
        :class="[isSendingDisabled || !inputMessage.trim() ? 'text-gray-500' : 'text-white']"
      />
      <span
        class="ml-1 text-sm"
        :class="[isSendingDisabled || !inputMessage.trim() ? 'text-gray-500' : 'text-white']"
      >
        {{ isSendingDisabled ? '发送中' : isReplying ? '回复中' : '发送' }}
      </span>
    </div>
  </div>
</template>

<style scoped lang="scss">
.message_body {
  height: calc(100% - 120px);

  .mb-4:last-child {
    margin-bottom: 2rem;
  }
}

.inputs {
  border: 1px solid rgba(128, 128, 128, 0.1);
  border-right: none;
  width: calc(100% - 20px);
}

.breathing {
  animation: breathing 2s infinite;
}

@keyframes breathing {
  0%,
  100% {
    background-color: rgba(255, 0, 0, 0.4);
  }
  50% {
    background-color: rgba(255, 0, 0);
  }
}
</style>
